use crate::config::database_config::DatabaseConfig;
use crate::config::redis_config::RedisConfig;
use crate::config::thread_pool_config::ThreadPoolConfig;
use crate::utils::dir::get_project_root;
use config::{Config, Environment, File};
use serde::Deserialize;
use std::collections::HashMap;
use std::env;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;

///系统配置
#[derive(Debug, Deserialize, Clone)]
pub struct AppConfig {
    /// 日志配置地址
    pub log4rs: Option<String>,
    /// Redis配置
    pub redis: RedisConfig,
    /// Database配置
    pub database: DatabaseConfig,
    /// Database配置
    pub thread_pool: ThreadPoolConfig,
}

/// 系统配置实现
impl AppConfig {
    /// 加载配置项
    /// 默认加载根目录（src同级目录）或.exe同级目录下的settings文件夹的default.toml配置，优先级最低
    /// 可通过根目录（src同级目录）或.exe同级目录下的.env文件指定RUST_ENV、SETTINGS_PATH配置项指定路径，依次加载default、rust_env的配置，优先级高于默认值
    /// 也可通过环境变量指定RUST_ENV、SETTINGS_PATH配置，再依次加载，优先级最高
    pub fn load() -> Self {
        let root_path = get_project_root().unwrap(); // 获取current_exe路径
                                                     // println!("root_path -> {:?}", &root_path);

        let environment = load_env(&root_path); // 加载current_exe/.env文件

        // 默认取dev配置
        let mut run_mode = String::from("dev");
        // 默认取current_exe/settings/*下的配置文件
        let mut run_setting_path = String::from(root_path.join("settings").to_str().unwrap());

        let rust_env = String::from("RUST_ENV");
        let settings_path = String::from("SETTINGS_PATH");

        let mut env_builder = Config::builder()
            // 设置默认配置
            .set_default(rust_env.clone(), run_mode.clone())
            .unwrap()
            .set_default(settings_path.clone(), run_setting_path.clone())
            .unwrap()
            .add_source(environment.clone()); // .env配置的优先级高于默认配置

        // 环境变量中的配置高于.env文件配置
        if let Ok(val) = env::var(rust_env.clone()) {
            env_builder = env_builder.set_override(rust_env.clone(), val).unwrap();
        }
        if let Ok(val) = env::var(settings_path.clone()) {
            env_builder = env_builder
                .set_override(settings_path.clone(), val)
                .unwrap();
        }

        let env_config = env_builder.build().unwrap();
        run_mode = env_config.get(&rust_env).unwrap();
        run_setting_path = env_config.get(&settings_path).unwrap();
        println!("run_mode -> {run_mode}");

        // 获取配置文件目录
        let settings_dir = PathBuf::from(&run_setting_path);
        println!("config_dir -> {:?}", &settings_dir);

        // 获取配置
        let config = Config::builder()
            // 添加默认配置
            .add_source(File::from(settings_dir.join("default.toml")))
            // 添加自定义前缀配置
            .add_source(File::from(settings_dir.join(format!("{run_mode}.toml"))).required(false))
            .add_source(env_config)
            .build()
            .unwrap();
        // println!("{:?}", &config);

        // 反序列化
        let app_config: AppConfig = config.try_deserialize().unwrap();
        println!("AppConfig load -> {:?}", &app_config);
        app_config
    }
}

/// 加载.env配置文件
pub fn load_env(root_path: &PathBuf) -> Environment {
    let mut env_vars = HashMap::new();
    if let Ok(file) = std::fs::File::open(root_path.join(".env")) {
        let reader = BufReader::new(file);
        for line in reader.lines() {
            if let Ok(line_str) = line {
                if let Some(pos) = line_str.find('=') {
                    let key = line_str[0..pos].trim();
                    let value = line_str[pos + 1..].trim();
                    env_vars.insert(key.to_string(), value.to_string());
                }
            }
        }
    }

    // println!("env_vars -> {:?}", &env_vars);
    Environment::default().source(Some(env_vars))
}
